package com.fishv.fishvdianping.service.impl;


import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.fishv.fishvdianping.common.ErrorCode;
import com.fishv.fishvdianping.common.RedisConstant;
import com.fishv.fishvdianping.common.Result;
import com.fishv.fishvdianping.mapper.ShopMapper;
import com.fishv.fishvdianping.model.domain.Shop;
import com.fishv.fishvdianping.service.ShopService;
import com.fishv.fishvdianping.utils.ThrowUtils;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.util.concurrent.TimeUnit;

/**
* @author yuwei
* @description 针对表【tb_shop】的数据库操作Service实现
* @createDate 2024-10-20 22:50:45
*/
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop>
    implements ShopService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public Shop getById(Long id) {
        //查询缓存
        String key = RedisConstant.SHOP_CACHE_KEY + id;
        if(!stringRedisTemplate.hasKey(key)){
            //查询数据库
            Shop shop =  query().eq("id",id).one();
            if(shop==null){
                stringRedisTemplate.opsForValue().set(key,"", RedisConstant.SHOP_CACHE_TTL, TimeUnit.MINUTES);
                return null;
            }
            //存入缓存
            stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop), RedisConstant.SHOP_CACHE_TTL, TimeUnit.MINUTES);
            return shop;
        }
        String shopJson = stringRedisTemplate.opsForValue().get(key);

        if(StringUtils.isNotEmpty(shopJson)){
          return   JSONUtil.toBean(shopJson,Shop.class);
        }
        return null;
    }
    public Shop queryWithMutex(Long id){
        //查询缓存
        String key = RedisConstant.SHOP_CACHE_KEY + id;
        if(!stringRedisTemplate.hasKey(key)){
            //获取锁
            String lockKey = "lock:shop:" + id;
            if(!tryLock(key)){
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                return queryWithMutex(id);
            }

            //查询数据库
            Shop shop =  query().eq("id",id).one();
            if(shop==null){
                stringRedisTemplate.opsForValue().set(key,"", RedisConstant.SHOP_CACHE_TTL, TimeUnit.MINUTES);
                unLock(key);
                return null;
            }
            //存入缓存
            stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop), RedisConstant.SHOP_CACHE_TTL, TimeUnit.MINUTES);
            unLock(key);
            return shop;
        }
        String shopJson = stringRedisTemplate.opsForValue().get(key);

        if(StringUtils.isNotEmpty(shopJson)){
            return   JSONUtil.toBean(shopJson,Shop.class);
        }
        return null;
    }
    public Boolean tryLock(String key){
        return stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 1, TimeUnit.SECONDS);
    }
    public void unlock(String key){
        stringRedisTemplate.delete(key);
    }
    public void unLock(String key){
        stringRedisTemplate.delete(key);
    }

    @Override
    @Transactional
    public String update(Shop shop) {
        Long id = shop.getId();
        // 1.更新数据库
       Boolean res =  updateById(shop);
        ThrowUtils.throwIf(!res, ErrorCode.SYSTEM_ERROR, "更新失败");
        // 2.删除缓存
        stringRedisTemplate.delete(RedisConstant.SHOP_CACHE_KEY + id);
        return "更新成功";
    }

}




